void SessionPriv::setupSidePanel() {
	auto sidePanelDock=new QDockWidget{"Side Panel", session};
	session->addDockWidget(Qt::LeftDockWidgetArea, sidePanelDock, Qt::Vertical);
	auto sidePanel=new QWidget{sidePanelDock, 0};
	sidePanelDock->setWidget(sidePanel);
	auto glayout=new QGridLayout{sidePanel};
	glayout->setRowStretch(2, 1);
	glayout->setColumnStretch(1, 1);

	curLeft=new QPushButton{QIcon{":/images/breeze/arrow-left-double.svg"}, "", sidePanel};
	glayout->addWidget(curLeft, 0, 0, 1, 1);
	sliderCur=new QSlider{Qt::Horizontal, sidePanel};
	glayout->addWidget(sliderCur, 0, 1, 1, 1);
	sliderCur->setMinimumWidth(64);
	sliderCur->setSingleStep(1);
	sliderCur->setPageStep(1);
	curRight=new QPushButton{QIcon{":/images/breeze/arrow-right-double.svg"}, "", sidePanel};
	glayout->addWidget(curRight, 0, 2, 1, 1);
	tgtLeft=new QPushButton{QIcon{":/images/breeze/arrow-left-double.svg"}, "", sidePanel};
	glayout->addWidget(tgtLeft, 1, 0, 1, 1);
	sliderTgt=new QSlider{Qt::Horizontal, sidePanel};
	glayout->addWidget(sliderTgt, 1, 1, 1, 1);
	sliderTgt->setMinimumWidth(64);
	sliderTgt->setSingleStep(1);
	sliderTgt->setPageStep(1);
	tgtRight=new QPushButton{QIcon{":/images/breeze/arrow-right-double.svg"}, "", sidePanel};
	glayout->addWidget(tgtRight, 1, 2, 1, 1);

	QObject::connect(sliderCur, &QSlider::valueChanged,
			[this](int v)->void { curLeft->setEnabled(v!=sliderCur->minimum()); curRight->setEnabled(v!=sliderCur->maximum()); });
	QObject::connect(sliderTgt, &QSlider::valueChanged,
			[this](int v)->void { tgtLeft->setEnabled(v!=sliderTgt->minimum()); tgtRight->setEnabled(v!=sliderTgt->maximum()); });
	QObject::connect(sliderCur, &QSlider::valueChanged, session, &Session::setPositionCur);
	QObject::connect(sliderTgt, &QSlider::valueChanged, session, &Session::setPositionTgt);
	QObject::connect(curLeft, &QPushButton::clicked,
			[this]()->void { sliderCur->setValue(sliderCur->minimum()); });
	QObject::connect(curRight, &QPushButton::clicked,
			[this]()->void { sliderCur->setValue(sliderCur->maximum()); });
	QObject::connect(tgtLeft, &QPushButton::clicked,
			[this]()->void { sliderTgt->setValue(sliderTgt->minimum()); });
	QObject::connect(tgtRight, &QPushButton::clicked,
			[this]()->void { sliderTgt->setValue(sliderTgt->maximum()); });

	sliderCur->setEnabled(false);
	curLeft->setEnabled(false);
	curRight->setEnabled(false);
	sliderTgt->setEnabled(false);
	tgtLeft->setEnabled(false);
	tgtRight->setEnabled(false);

	listView=new QTreeView{sidePanel};
	glayout->addWidget(listView, 2, 0, 1, 3);
	listView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
	listView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
	listView->setSelectionBehavior(QAbstractItemView::SelectRows);
	listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
	listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
	listView->setContextMenuPolicy(Qt::CustomContextMenu);
	listView->setAllColumnsShowFocus(true);
	QObject::connect(listView, &QTreeView::customContextMenuRequested, [this](const QPoint& pt) { popupList->popup(listView->mapToGlobal(pt)); });
	listView->setEnabled(false);
}

void SessionPriv::setupAnnotPanel() {
	auto annotDock=new QDockWidget{"Annotation", session};
	session->addDockWidget(Qt::RightDockWidgetArea, annotDock, Qt::Vertical);
	auto annotPanel=new QWidget{annotDock, 0};
	annotDock->setWidget(annotPanel);
	auto vlayout=new QVBoxLayout{annotPanel};

	auto hlayout=new QHBoxLayout{};
	vlayout->addLayout(hlayout, 0);
	auto label=new QLabel{"Data", annotPanel};
	hlayout->addWidget(label, 0);
	annotList=new QComboBox{annotPanel};
	hlayout->addWidget(annotList, 1);
	annotList->setEditable(false);
	annotList->setCurrentIndex(-1);
	annot_map=-1;
	QObject::connect(annotList, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [this](int i) { this->annotListChanged(i); });

	annotHeader=new QListWidget{annotPanel};
	vlayout->addWidget(annotHeader, 1);
	//annotHeader->setEditable(false);
	annotHeader->setCurrentRow(-1);

	annotView=new QTreeView{annotPanel};
	vlayout->addWidget(annotView, 2);

	annotView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
	annotView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
	annotView->setSelectionBehavior(QAbstractItemView::SelectRows);
	annotView->setSelectionMode(QAbstractItemView::ExtendedSelection);
	annotView->setEditTriggers(QAbstractItemView::NoEditTriggers);
	annotView->setContextMenuPolicy(Qt::CustomContextMenu);

	//QObject::connect(annotView, &QTreeView::customContextMenuRequested, [this](const QPoint& pt) { popupList->popup(annotView->mapToGlobal(pt)); });
	annotView->setEnabled(false);
}
void SessionPriv::setupStatusBar() {
	statusBar=new QStatusBar{session};
	session->setStatusBar(statusBar);

	statLabel=new QLabel{"Loading...", statusBar};
	statusBar->addWidget(statLabel, 0);

	progr=new QProgressBar{statusBar};
	progr->setTextVisible(false);
	progr->setMinimumWidth(160);
	auto spol=progr->sizePolicy();
	spol.setHorizontalPolicy(QSizePolicy::Fixed);
	progr->setSizePolicy(spol);
	statusBar->addPermanentWidget(progr, 0);
}
void SessionPriv::setupMenuBarAndToolBar() {
	auto& tracerActions=Tracer::instance()->tracerActions();
	auto recentMenu=Tracer::instance()->recentMenu();
	auto recoverMenu=Tracer::instance()->recoverMenu();

	auto menuBar=new QMenuBar{session};
	session->setMenuBar(menuBar);

	auto menuFile=new QMenu{"&File", session};
	menuBar->addMenu(menuFile);
	menuFile->addAction(tracerActions[SESSION_NEW]);
	menuFile->addAction(tracerActions[SESSION_OPEN]);
	menuFile->addMenu(recentMenu);
	menuFile->addMenu(recoverMenu);
	menuFile->addSeparator();
	menuFile->addAction(actions[SESSION_SAVE]);
	menuFile->addAction(actions[SESSION_SAVE_AS]);
	menuFile->addMenu(menuMisc);
	menuFile->addAction(actions[SESSION_CLOSE]);
	menuFile->addSeparator();
	menuFile->addAction(tracerActions[TRACER_SETTINGS]);
	menuFile->addSeparator();
	menuFile->addAction(tracerActions[TRACER_QUIT]);

	auto menuEdit=new QMenu{"&Edit", session};
	menuBar->addMenu(menuEdit);
	menuEdit->addAction(actions[EDIT_UNDO]);
	menuEdit->addAction(actions[EDIT_REDO]);
	menuEdit->addSeparator();
	menuEdit->addAction(actions[EDIT_CHANGE_TYPE]);
	menuEdit->addAction(actions[EDIT_CHANGE_MARK]);
	menuEdit->addAction(actions[EDIT_CHANGE_SIZE]);
	menuEdit->addSeparator();
	menuEdit->addAction(actions[EDIT_IMPORT_FNT]);
	menuEdit->addAction(actions[EDIT_IMPORT_SWC]);
	menuEdit->addSeparator();
	menuEdit->addAction(actions[EDIT_ABORT]);

	auto menuPos=new QMenu{"&Position", session};
	menuBar->addMenu(menuPos);
	menuPos->addAction(actions[EDIT_GOTO_TARGET]);
	menuPos->addAction(actions[EDIT_PICK_CURRENT]);
	menuPos->addAction(actions[EDIT_GOTO_POS]);
	menuPos->addSeparator();
	menuPos->addAction(actions[EDIT_LOAD_DATA]);
	menuPos->addAction(actions[EDIT_LOAD_DATA_AUTO]);

	auto menuNeuron=new QMenu{"&Neuron", session};
	menuBar->addMenu(menuNeuron);
	menuNeuron->addAction(actions[EDIT_NEW_NEURON]);
	menuNeuron->addSeparator();
	menuNeuron->addAction(actions[EDIT_RENAME_NEURON]);
	menuNeuron->addSeparator();
	menuNeuron->addAction(actions[EDIT_DEL_NEURONS]);
	menuNeuron->addAction(actions[EDIT_PURGE_NEURONS]);

	auto menuTracing=new QMenu{"&Tracing", session};
	menuBar->addMenu(menuTracing);
	menuTracing->addAction(actions[TRACING_FIND]);
	menuTracing->addAction(actions[TRACING_CONNECT]);
	menuTracing->addAction(actions[TRACING_REFINE]);
	menuTracing->addSeparator();
	menuTracing->addAction(actions[TRACING_DONE]);
	menuTracing->addAction(actions[TRACING_BRANCH]);
	menuTracing->addAction(actions[TRACING_EXTEND]);
	menuTracing->addSeparator();
	menuTracing->addAction(actions[TRACING_MARK1]);
	menuTracing->addAction(actions[TRACING_MARK2]);
	menuTracing->addAction(actions[TRACING_MARK3]);
	menuTracing->addAction(actions[TRACING_MARK_CLEAR]);
	menuTracing->addSeparator();
	menuTracing->addAction(actions[TRACING_DELETE]);

	auto menuView=new QMenu{"&View", session};
	menuBar->addMenu(menuView);
	menuView->addAction(actions[VIEW_SLICE]);
	menuView->addAction(actions[VIEW_EDGE]);

	auto menuDebug=new QMenu{"&Debug", session};
	menuBar->addMenu(menuDebug);
	menuDebug->addAction(actions[DEBUG_SAVE_CUBE]);
	menuDebug->addAction(actions[DEBUG_SCREENSHOT]);
	menuDebug->addAction(actions[DEBUG_START_ROTATE]);

	auto menuHelp=new QMenu{"&Help", session};
	menuBar->addMenu(menuHelp);
	menuHelp->addAction(tracerActions[TRACER_MANUAL]);
#ifndef BUILD_APPLE
	menuHelp->addSeparator();
#endif
	menuHelp->addAction(tracerActions[TRACER_ABOUT]);

	auto toolBar=new QToolBar{"Toolbar", session};
	session->addToolBar(Qt::TopToolBarArea, toolBar);
	toolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
	toolBar->addAction(actions[SESSION_NEW]);
	toolBar->addAction(actions[SESSION_OPEN]);
	toolBar->addAction(actions[SESSION_SAVE]);
	toolBar->addSeparator();
	toolBar->addAction(actions[EDIT_UNDO]);
	toolBar->addAction(actions[EDIT_REDO]);
	toolBar->addAction(actions[EDIT_ABORT]);
	toolBar->addSeparator();
	toolBar->addAction(actions[TRACING_FIND]);
	toolBar->addAction(actions[TRACING_CONNECT]);
	toolBar->addAction(actions[TRACING_REFINE]);
	toolBar->addSeparator();
	toolBar->addAction(actions[TRACING_DONE]);
	toolBar->addAction(actions[TRACING_BRANCH]);
	toolBar->addAction(actions[TRACING_EXTEND]);
	toolBar->addSeparator();
	toolBar->addAction(actions[TRACING_MARK1]);
	toolBar->addAction(actions[TRACING_MARK2]);
	toolBar->addAction(actions[TRACING_MARK3]);
	toolBar->addAction(actions[TRACING_MARK_CLEAR]);
	toolBar->addSeparator();
	toolBar->addAction(actions[TRACING_DELETE]);
}
void SessionPriv::setupActions() {
	actions[SESSION_SAVE]=new QAction{QIcon{":/images/breeze/document-save.svg"}, "&Save", session};
	actions[SESSION_SAVE]->setStatusTip("Save changes to the current session");
	actions[SESSION_SAVE]->setShortcut(QKeySequence{"Ctrl+S"});
	QObject::connect(actions[SESSION_SAVE], &QAction::triggered, session, &Session::saveSession);

	actions[SESSION_SAVE_AS]=new QAction{QIcon{":/images/breeze/document-save-as.svg"}, "Save &as...", session};
	actions[SESSION_SAVE_AS]->setStatusTip("Save the current session to another file");
	actions[SESSION_SAVE_AS]->setShortcut(QKeySequence{"Ctrl+Shift+S"});
	QObject::connect(actions[SESSION_SAVE_AS], &QAction::triggered, session, &Session::saveSessionAs);

	actions[SESSION_CLOSE]=new QAction{QIcon{":/images/breeze/view-close.svg"}, "&Close", session};
	actions[SESSION_CLOSE]->setStatusTip("Close the current session");
	actions[SESSION_CLOSE]->setShortcut(QKeySequence{"Ctrl+W"});
	QObject::connect(actions[SESSION_CLOSE], &QAction::triggered, session, &Session::closeSession);

	actions[EDIT_UNDO]=new QAction{QIcon{":/images/breeze/edit-undo.svg"}, "&Undo", session};
	actions[EDIT_UNDO]->setStatusTip("Revert most rescent action");
	actions[EDIT_UNDO]->setShortcut(QKeySequence{"Ctrl+Z"});
	QObject::connect(actions[EDIT_UNDO], &QAction::triggered, session, &Session::undoCommand);

	actions[EDIT_REDO]=new QAction{QIcon{":/images/breeze/edit-redo.svg"}, "&Redo", session};
	actions[EDIT_REDO]->setStatusTip("Re-perform the last reverted action");
	actions[EDIT_REDO]->setShortcut(QKeySequence{"Ctrl+Shift+Z"});
	QObject::connect(actions[EDIT_REDO], &QAction::triggered, session, &Session::redoCommand);

	actions[EDIT_GOTO_POS]=new QAction{QIcon{":/images/generated/goto-pos.svg"}, "&Goto position...", session};
	actions[EDIT_GOTO_POS]->setStatusTip("Jump to a given position");
	actions[EDIT_GOTO_POS]->setShortcut(QKeySequence{"Ctrl+G"});
	QObject::connect(actions[EDIT_GOTO_POS], &QAction::triggered, session, &Session::jumpPosition);

	actions[EDIT_GOTO_TARGET]=new QAction{QIcon{":/images/generated/goto-target.svg"}, "Goto &target", session};
	actions[EDIT_GOTO_TARGET]->setStatusTip("Jump to the target position");
	actions[EDIT_GOTO_TARGET]->setShortcut(QKeySequence{"Ctrl+Shift+G"});
	QObject::connect(actions[EDIT_GOTO_TARGET], &QAction::triggered, session, &Session::jumpToTarget);

	actions[EDIT_PICK_CURRENT]=new QAction{QIcon{":/images/generated/pick-current.svg"}, "&Pick current", session};
	actions[EDIT_PICK_CURRENT]->setStatusTip("Pick the current position");
	actions[EDIT_PICK_CURRENT]->setShortcut(QKeySequence{"Ctrl+C"});
	QObject::connect(actions[EDIT_PICK_CURRENT], &QAction::triggered, session, &Session::pickCurrent);

	actions[EDIT_LOAD_DATA]=new QAction{QIcon{":/images/breeze/cloud-download.svg"}, "&Load data", session};
	actions[EDIT_LOAD_DATA]->setStatusTip("Load data around the current position");
	actions[EDIT_LOAD_DATA]->setShortcut(QKeySequence{"Ctrl+Shift+G"});
	QObject::connect(actions[EDIT_LOAD_DATA], &QAction::triggered, session, &Session::startDownloadCube);

	actions[EDIT_LOAD_DATA_AUTO]=new QAction{QIcon{":/images/breeze/cloud-download-auto.svg"}, "Load data &auto", session};
	actions[EDIT_LOAD_DATA_AUTO]->setCheckable(true);
	actions[EDIT_LOAD_DATA_AUTO]->setChecked(loadDataAuto);
	actions[EDIT_LOAD_DATA_AUTO]->setStatusTip("Load data automatically");
	actions[EDIT_LOAD_DATA_AUTO]->setShortcut(QKeySequence{""});
	QObject::connect(actions[EDIT_LOAD_DATA_AUTO], &QAction::toggled, session, &Session::toggleAutoDownload);

	actions[EDIT_CHANGE_TYPE]=new QAction{QIcon{":/images/generated/change-type.svg"}, "&Change neurite type...", session};
	actions[EDIT_CHANGE_TYPE]->setStatusTip("Change the type of the picked neurite");
	actions[EDIT_CHANGE_TYPE]->setShortcut(QKeySequence{"Ctrl+T"});
	QObject::connect(actions[EDIT_CHANGE_TYPE], &QAction::triggered, session, &Session::changeType);

	actions[EDIT_CHANGE_MARK]=new QAction{QIcon{":/images/generated/change-mark.svg"}, "&Change node type...", session};
	actions[EDIT_CHANGE_MARK]->setStatusTip("Change the type of the picked node");
	actions[EDIT_CHANGE_MARK]->setShortcut(QKeySequence{"Ctrl+M"});
	QObject::connect(actions[EDIT_CHANGE_MARK], &QAction::triggered, session, &Session::changeMark);

	actions[EDIT_CHANGE_SIZE]=new QAction{QIcon{":/images/generated/change-size.svg"}, "&Resize node...", session};
	actions[EDIT_CHANGE_SIZE]->setStatusTip("Change the size of the picked node");
	actions[EDIT_CHANGE_SIZE]->setShortcut(QKeySequence{"Ctrl+R"});
	QObject::connect(actions[EDIT_CHANGE_SIZE], &QAction::triggered, session, &Session::changeSize);

	actions[EDIT_NEW_NEURON]=new QAction{QIcon{":/images/generated/new-neuron.svg"}, "&New neuron", session};
	actions[EDIT_NEW_NEURON]->setStatusTip("Create a new neuron with soma at the target position");
	actions[EDIT_NEW_NEURON]->setShortcut(QKeySequence{"Ctrl+Shift+N"});
	QObject::connect(actions[EDIT_NEW_NEURON], &QAction::triggered, session, &Session::createNeuron);

	actions[EDIT_RENAME_NEURON]=new QAction{QIcon{":/images/breeze/edit-rename.svg"}, "Re&name Neuron...", session};
	actions[EDIT_RENAME_NEURON]->setStatusTip("Rename the current neuron");
	actions[EDIT_RENAME_NEURON]->setShortcut(QKeySequence{"Ctrl+R"});
	QObject::connect(actions[EDIT_RENAME_NEURON], &QAction::triggered, session, &Session::renameNeuron);

	actions[EDIT_DEL_NEURONS]=new QAction{QIcon{":/images/generated/del-neurons.svg"}, "&Remove neurons", session};
	actions[EDIT_DEL_NEURONS]->setStatusTip("Remove selected neurons");
	actions[EDIT_DEL_NEURONS]->setShortcut(QKeySequence{"Ctrl+X"});
	QObject::connect(actions[EDIT_DEL_NEURONS], &QAction::triggered, session, &Session::removeNeurons);

	actions[EDIT_PURGE_NEURONS]=new QAction{QIcon{":/images/generated/purge-neurons.svg"}, "&Purge neurons", session};
	actions[EDIT_PURGE_NEURONS]->setStatusTip("Remove selected neurons and associated edges");
	actions[EDIT_PURGE_NEURONS]->setShortcut(QKeySequence{"Ctrl+Shift+X"});
	QObject::connect(actions[EDIT_PURGE_NEURONS], &QAction::triggered, session, &Session::purgeNeurons);

	actions[EDIT_IMPORT_FNT]=new QAction{QIcon{":/images/breeze/document-import.svg"}, "&Import FNT...", session};
	actions[EDIT_IMPORT_FNT]->setStatusTip("Import from FNT files");
	actions[EDIT_IMPORT_FNT]->setShortcut(QKeySequence{"Ctrl+I"});
	QObject::connect(actions[EDIT_IMPORT_FNT], &QAction::triggered, session, &Session::importFnt);
	actions[EDIT_IMPORT_SWC]=new QAction{QIcon{":/images/breeze/document-import.svg"}, "&Import SWC...", session};
	actions[EDIT_IMPORT_SWC]->setStatusTip("Import from SWC files");
	actions[EDIT_IMPORT_SWC]->setShortcut(QKeySequence{"Ctrl+Shift+I"});
	QObject::connect(actions[EDIT_IMPORT_SWC], &QAction::triggered, session, &Session::importSwc);

	actions[TRACING_FIND]=new QAction{QIcon{":/images/generated/find-path.svg"}, "&Find", session};
	actions[TRACING_FIND]->setStatusTip("Find paths starting from the current position");
	actions[TRACING_FIND]->setShortcut(QKeySequence{"F"});
	QObject::connect(actions[TRACING_FIND], &QAction::triggered, session, &Session::findPath);

	actions[TRACING_CONNECT]=new QAction{QIcon{":/images/generated/connect-points.svg"}, "&Connect", session};
	actions[TRACING_CONNECT]->setStatusTip("Find a path connecting the current position and the target position");
	actions[TRACING_CONNECT]->setShortcut(QKeySequence{"C"});
	QObject::connect(actions[TRACING_CONNECT], &QAction::triggered, session, &Session::connectPoints);

	actions[TRACING_REFINE]=new QAction{QIcon{":/images/generated/refine-path.svg"}, "&Refine", session};
	actions[TRACING_REFINE]->setStatusTip("Refine the putative path");
	actions[TRACING_REFINE]->setShortcut(QKeySequence{"R"});
	QObject::connect(actions[TRACING_REFINE], &QAction::triggered, session, &Session::refinePath);

	actions[TRACING_DONE]=new QAction{QIcon{":/images/generated/tracing-done.svg"}, "&Done", session};
	actions[TRACING_DONE]->setStatusTip("Declare the node at the current position as finished.");
	actions[TRACING_DONE]->setShortcut(QKeySequence{"D"});
	QObject::connect(actions[TRACING_DONE], &QAction::triggered, session, &Session::finishBranch);

	actions[TRACING_BRANCH]=new QAction{QIcon{":/images/generated/tracing-branch.svg"}, "&Branch", session};
	actions[TRACING_BRANCH]->setStatusTip("Create a new branch with the putative path");
	actions[TRACING_BRANCH]->setShortcut(QKeySequence{"B"});
	QObject::connect(actions[TRACING_BRANCH], &QAction::triggered, session, &Session::createBranch);

	actions[TRACING_EXTEND]=new QAction{QIcon{":/images/generated/tracing-extend.svg"}, "Extend (& )", session};
	actions[TRACING_EXTEND]->setStatusTip("Extend the current edge with the putative path");
	actions[TRACING_EXTEND]->setShortcut(QKeySequence{"Space"});
	QObject::connect(actions[TRACING_EXTEND], &QAction::triggered, session, &Session::extendBranch);

	actions[TRACING_MARK1]=new QAction{QIcon{":/images/generated/mark1.svg"}, "Mark &1", session};
	actions[TRACING_MARK1]->setStatusTip("Set mark NO. 1 at the target position");
	actions[TRACING_MARK1]->setShortcut(QKeySequence{"1"});
	QObject::connect(actions[TRACING_MARK1], &QAction::triggered, session, &Session::setMark1);

	actions[TRACING_MARK2]=new QAction{QIcon{":/images/generated/mark2.svg"}, "Mark &2", session};
	actions[TRACING_MARK2]->setStatusTip("Set mark NO. 2 at the target position");
	actions[TRACING_MARK2]->setShortcut(QKeySequence{"2"});
	QObject::connect(actions[TRACING_MARK2], &QAction::triggered, session, &Session::setMark2);

	actions[TRACING_MARK3]=new QAction{QIcon{":/images/generated/mark3.svg"}, "Mark &3", session};
	actions[TRACING_MARK3]->setStatusTip("Set mark NO. 3 at the target position");
	actions[TRACING_MARK3]->setShortcut(QKeySequence{"3"});
	QObject::connect(actions[TRACING_MARK3], &QAction::triggered, session, &Session::setMark3);

	actions[TRACING_MARK_CLEAR]=new QAction{QIcon{":/images/generated/mark0.svg"}, "Clear mark (&0)", session};
	actions[TRACING_MARK_CLEAR]->setStatusTip("Clear the mark at the target position");
	actions[TRACING_MARK_CLEAR]->setShortcut(QKeySequence{"0"});
	QObject::connect(actions[TRACING_MARK_CLEAR], &QAction::triggered, session, &Session::clearMark);

	actions[TRACING_DELETE]=new QAction{QIcon{":/images/breeze/edit-cut.svg"}, "Delete (&X)", session};
	actions[TRACING_DELETE]->setStatusTip("Delete an edge or part of an edge");
	actions[TRACING_DELETE]->setShortcut(QKeySequence{"X"});
	QObject::connect(actions[TRACING_DELETE], &QAction::triggered, session, &Session::removeEdge);

	actions[VIEW_SLICE]=new QAction{QIcon{":/images/generated/view-slice.svg"}, "&Slice", session};
	actions[VIEW_SLICE]->setCheckable(true);
	actions[VIEW_SLICE]->setChecked(false);
	actions[VIEW_SLICE]->setStatusTip("Enable slice mode");
	actions[VIEW_SLICE]->setShortcut(QKeySequence{"S"});
	QObject::connect(actions[VIEW_SLICE], &QAction::toggled, viewer, &Viewer::setSliceMode);
	actions[VIEW_EDGE]=new QAction{QIcon{":/images/generated/view-edge.svg"}, "Ed&ge", session};
	actions[VIEW_EDGE]->setCheckable(true);
	actions[VIEW_EDGE]->setChecked(true);
	actions[VIEW_EDGE]->setStatusTip("Show edges");
	actions[VIEW_EDGE]->setShortcut(QKeySequence{"G"});
	QObject::connect(actions[VIEW_EDGE], &QAction::toggled, viewer, &Viewer::setEdgeVisibility);


	actions[EDIT_ABORT]=new QAction{QIcon{":/images/breeze/process-stop.svg"}, "&Abort", session};
	actions[EDIT_ABORT]->setStatusTip("Abort current computation or downloading task");
	actions[EDIT_ABORT]->setShortcut(QKeySequence{"A"});
	QObject::connect(actions[EDIT_ABORT], &QAction::triggered, session, &Session::abortOperation);

	actions[DEBUG_SAVE_CUBE]=new QAction{"Save &Cube...", session};
	actions[DEBUG_SAVE_CUBE]->setStatusTip("Save current cube");
	actions[DEBUG_SAVE_CUBE]->setShortcut(QKeySequence{"Ctrl+Shift+Alt+D, C"});
	QObject::connect(actions[DEBUG_SAVE_CUBE], &QAction::triggered, session, &Session::saveCurrentCube);

	actions[DEBUG_SCREENSHOT]=new QAction{"Take &Screenshot...", session};
	actions[DEBUG_SCREENSHOT]->setStatusTip("Take a screenshot of the current 3D viewer");
	actions[DEBUG_SCREENSHOT]->setShortcut(QKeySequence{"Ctrl+Shift+Alt+D, S"});
	QObject::connect(actions[DEBUG_SCREENSHOT], &QAction::triggered, session, &Session::takeScreenshot);

	actions[DEBUG_START_ROTATE]=new QAction{"&Rotate", session};
	actions[DEBUG_START_ROTATE]->setStatusTip("Start/stop rotating the view");
	actions[DEBUG_START_ROTATE]->setShortcut(QKeySequence{"Ctrl+Shift+Alt+D, R"});
	QObject::connect(actions[DEBUG_START_ROTATE], &QAction::triggered, session, &Session::toggleRotate);

	for(int i=0; i<SESSION_ACTION_NUM; i++) {
		//actions[i]->setShortcutContext(false);
		actions[i]->setEnabled(false);
	}
}
void SessionPriv::setupMenus() {
	popupViewer=new QMenu{"Context Menu", session};
	popupViewer->addAction(actions[EDIT_GOTO_TARGET]);
	popupViewer->addAction(actions[EDIT_PICK_CURRENT]);
	popupViewer->addAction(actions[EDIT_GOTO_POS]);
	popupViewer->addSeparator();
	popupViewer->addAction(actions[EDIT_CHANGE_TYPE]);
	popupViewer->addAction(actions[EDIT_CHANGE_MARK]);
	popupViewer->addAction(actions[EDIT_CHANGE_SIZE]);
	popupViewer->addSeparator();
	popupViewer->addAction(actions[EDIT_NEW_NEURON]);
	popupViewer->addSeparator();
	popupViewer->addAction(actions[EDIT_ABORT]);

	popupList=new QMenu{"Context Menu", session};
	popupList->addAction(actions[EDIT_NEW_NEURON]);
	popupList->addSeparator();
	popupList->addAction(actions[EDIT_RENAME_NEURON]);
	popupList->addSeparator();
	popupList->addAction(actions[EDIT_DEL_NEURONS]);
	popupList->addAction(actions[EDIT_PURGE_NEURONS]);
	popupList->addSeparator();
	popupList->addAction(actions[EDIT_IMPORT_FNT]);
	popupList->addAction(actions[EDIT_IMPORT_SWC]);

	menuMisc=new QMenu{"Misc...", session};
	//recentMenu->setIcon(QIcon{":/images/breeze/document-open-recent.svg"});
	auto& readers=PluginManager::instance()->graphReaders();
	for(int i=0; i<readers.size(); i++) {
			auto act=new QAction{readers[i].first->name, session};
			act->setData(i);
			act->setStatusTip(readers[i].first->desc);
			menuMisc->insertAction(nullptr, act);
			QObject::connect(act, &QAction::triggered, session, &Session::readGraph);
	}
	menuMisc->setEnabled(false);
}
